<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Runner-UP</title>
	
	<style type="text/css">
		body {
		    font-family: Arial, Helvetica;
		}
	</style>

	<style type="text/css">
	  @import url("http://www.google.com/uds/css/gsearch.css");
	  @import url("http://www.google.com/uds/solutions/localsearch/gmlocalsearch.css");
	</style>
	
	<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAs6H39exXc0c4AL0niyiOpRSF8nUD60A0leZcjynNwwPBVH5EHBSMh2_mQneLET84zgDYhLjH4Es3Hw" type="text/javascript"></script>
	<script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=ABQIAAAAs6H39exXc0c4AL0niyiOpRSF8nUD60A0leZcjynNwwPBVH5EHBSMh2_mQneLET84zgDYhLjH4Es3Hw" type="text/javascript"></script>
	<script src="http://www.google.com/uds/solutions/localsearch/gmlocalsearch.js" type="text/javascript"></script>
	<script src="js/prototype.js" type="text/javascript"></script>
    
	<script type="text/javascript">
    //<![CDATA[
  
	var runnerUp;
	function initialize() {
	  if (GBrowserIsCompatible()) {
		runnerUp = new RunnerUp();
        
		GEvent.bind(runnerUp.map, "click", runnerUp, runnerUp.mapClicked);
        
		runnerUp.loadExistingRouteNames();
		runnerUp.navigateToAddress(runnerUp.mainAddress);
	  }
	}
  
	function RunnerUp() {   
        /* Properties */ 
        
        this.mainAddress = "Mosevej 34, Ballerup, Denmark"; 
        this.route; // GPolyLine, will contain the route
        this.routeLength = 0; // In meters
        this.geocoder = new GClientGeocoder();		

        this.map = new GMap2($('map'));
        this.map.addControl(new GLargeMapControl());
        this.map.addControl(new GMapTypeControl());
        this.map.addControl(new google.maps.LocalSearch(), new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(10,20)));
        this.map.setMapType(G_HYBRID_MAP);

        /* Functions */
        
	    // Set center of map to specified address
	    this.navigateToAddress = function(address) {
	      if (this.geocoder) {
		    var tmp = this.map;
		    this.geocoder.getLatLng(address, function(point) {
			    if (!point) {
			      alert(address + " not found");
			    } else {
			      tmp.setCenter(point, 15);
			    }
		      }
		    );
	      }
	    }
	
	    this.mapClicked = function(overlay, latLng) {
	      this.expandRoute(latLng);
	    }
	
	    // Given a LatLng, create the corresponding piece of the route
	    this.expandRoute= function(latLng) {     
	      if (latLng) {
		    if(!this.route) {
		      // Route start
		      this.route = new GPolyline([latLng], "#0000ff", 3);
		      this.map.addOverlay(new GMarker(latLng));
		      this.map.addOverlay(this.route);
		    } else {
		      // Update route length
		      var previousVertex = this.route.getVertex(this.route.getVertexCount() - 1);
		      this.routeLength += latLng.distanceFrom(previousVertex);
		      
		      // Add new vertex to route
		      this.route.insertVertex(this.route.getVertexCount(), latLng);
		    }
		
		    this.updateDistance();
		    this.updateCalories();
		    this.updateFoodStats();
		    this.updateUndoButton();
	      }
	    }
	
        // Remove the last drawn vertex in the route 
	    this.revertRoute = function(numberOfVertices) {
            // Since GPolyLine.deleteVertex() has some weird restrictions, we'll just redraw the whole route
            var vertices = new Array();

            for(i = 0; i < this.route.getVertexCount(); i ++) {
                vertices.push(this.route.getVertex(i));
            } 
            
            vertices.pop();
            
            this.clearRoute();
            
            for(j = 0; j < vertices.length; j ++)
                this.expandRoute(vertices[j]);
    	}
	
	    // Update the distance indicator
	    this.updateDistance = function() {
	      if(this.routeLength == 0)
		    $('distance').innerHTML = "0 km.";
	      else {
		    var lengthInKm = ((this.routeLength / 1000) + "").match(/(\d+\.\d\d)/);
		    if(lengthInKm && lengthInKm.length > 0) {
		      $('distance').innerHTML = lengthInKm[0] + " km.";
		    }
	      }
	    }
	
	    // Update the table with food statistics
	    this.updateFoodStats = function() {
	      var calories = this.computeCalories();
	      {% for fooditem in fooditems %}
		    fooditem_{{forloop.counter}} = Math.round((calories / {{fooditem.kcals}}) * 10) / 10;
		    $('nr_of_{{fooditem.name}}').innerHTML = fooditem_{{forloop.counter}};
	      {% endfor %}
	    }
	
	    // Update the calories indicator
	    this.updateCalories = function() {
	      var calories = this.computeCalories();
	      $('kcal').innerHTML = calories + " kCal.";
	    }
	
	    // Compute nr of calories by route length and weight
	    this.computeCalories = function() {
	      var weight = ($('weight').value && $('weight').value != '0') ? $('weight').value : 0;
          var length = Math.round(this.routeLength);
	      var km = length/1000;
	      var kcal = (km * weight);
	      return Math.round(kcal);
	    }
	
	    // Enable/disable the Undo button
    	this.updateUndoButton = function() {
	        if(this.route.getVertexCount() == 0) {
	            Form.Element.disable($('undobutton'));
	            return;
	        }
            
            Form.Element.enable($('undobutton'));
	    }
	
	    // Save a route asynchronously  
    	this.saveRoute = function() {
	      var routename = $('routename').value;
	      
	      if(!routename || routename.length == 0) {
		    alert("Please define a name for this route");
	      } else if(this.routeLength == 0) {
		    alert("Please draw a route first");
	      } else {
		    // Create array of route vertices
		    var latLngArray = new Array();
		    for(i = 0; i < this.route.getVertexCount(); i++) {
		      var vertex = this.route.getVertex(i);
		      latLngArray.push(vertex.toUrlValue(15));  
		    }
		
		    var jsonifiedRoute = latLngArray.toJSON();
		
		    // Call server
		    new Ajax.Request('/routemanager', {
		      method: 'post',
		      parameters: {route: jsonifiedRoute, name: routename, action: 'save'},
              parameters: 'route=' + jsonifiedRoute + '&name=' + routename + '&action=save',
		      onSuccess: function(transport, json) {
			    if(transport.responseText.match('Success')) {
                    $('routeresult').innerHTML = "Route " + routename + " saved!";
                    $('existingroutes').insert('<option>' + routename + '</option>').selectedIndex = 0;  
                }
                else {
                    $('routeresult').innerHTML = "Error saving route: " + transport.responseText;
                }
		      }
		    });  
	      } 
	    }
        
        // Process the result of the loadRoute call. Clear existing route and draw loaded one. 
	    this.processLoadedRoute = function(transport, json) {
	      var response = null;
	      
	      try {
		    response = transport.responseText.evalJSON();	  
	      } catch (e) {
		    $('routeresult').innerHTML = "Error while loading route: " + transport.responseText;
		    return;
	      }
          runnerUp.clearRoute();
	
	      for(i = 0; i < response.vertices.length; i++) {
	        runnerUp.expandRoute(new GLatLng(response.vertices[i].lat, response.vertices[i].lng));
	      }
	
	      $('routeresult').innerHTML = "Successfully loaded route '" + response.routename + "'";
	    }
	
	    // Load a route asynchronously
	    this.loadRoute = function() {
          routeselector = $('existingroutes');
          if(routeselector.selectedIndex == 0)
            return;
            
	      var routename = routeselector[routeselector.selectedIndex].value;

	      new Ajax.Request('/routemanager', {
		      method: 'get',
		      parameters: {action: 'load', routename: routename},
		      onSuccess: this.processLoadedRoute
		    }); 
	    }
	
	    // Populate a dropdown box with existing route names
        this.loadExistingRouteNames = function() {
            new Ajax.Request('/routemanager', {
		      method: 'get',
		      parameters: {action: 'allnames'},
		      onSuccess: function(transport, json) {
                 var response = null; 
                 try {
                    response = transport.responseText.evalJSON();	  
                 } catch (e) {
                    reponse = 'Error';
                 }
              
                 for(i = 0; i < response.length; i++) {
                    $('existingroutes').insert('<option>' + response[i] + '</option>').selectedIndex = 0;                       
                 }
             }
		    });
        }
        
        // Remove route from map, reset all counters
	    this.clearRoute = function() {
	      this.route = undefined;
	      this.routeLength = 0;
	      this.map.clearOverlays();
	      this.updateDistance();
	      this.updateCalories();
	      this.updateFoodStats();
	    }
	
	}
    //]]>
    </script>
  </head>

  <body onload="initialize()" onunload="GUnload()">

  <div id="maincontainer" style="width:100%">
	<h3>Route planner</h3>
  
	<table style="width:100%">
	<tr>
		<td style="width:800px">
			<div id="map" style="width: 800px; height: 500px"></div>
		</td>
		<td style="vertical-align:top">
			<div id="actioncontainer" style="width: 100%">
				  <table style="width:100%">
					<tr>
						<td colspan="2"><input type="button" value="Undo last line" onclick="runnerUp.revertRoute(1)" id="undobutton" disabled/></td>
					</tr>
					<tr>
						<td colspan="2"><input type="button" value="Clear entire route" onclick="runnerUp.clearRoute()"/></td>
					</tr>
					<tr>
						<td style="width:25%"><input type="button" value="Save route" onclick="runnerUp.saveRoute()"/></td><td><input id="routename" type="text" size="10"></td>
					</tr>
					<tr>
						<td style="width:25%"><input type="button" value="Load route" onclick="runnerUp.loadRoute()"/></td><td><select id="existingroutes"><option selected="true">-- Select a route --</option></select></td>
					</tr>
					<tr>
						<td colspan="2"><div id="routeresult" style="position:relative">&nbsp;</div></td>
					</tr>
				  </table>
			</div>
		</td>
	</tr>
	</table>
	
	<div id="foods_container" style="width:800px; float:left">
	  <h3>Route statistics</h3>
	  
	  <div style="width:100%; height:30px; font-weight:bold">
		<div style="float:left">Distance:</div><div id="distance" style="float:left; padding-left:10px">0 km</div>
		<div style="float:left; padding-left:50px">Calories:</div><div id="kcal" style="float:left; padding-left:10px">0 kCal</div>
		<div style="float:right">
			<div style="float:left;">Weight (kg):</div><div style="float:left; padding-left:10px"><input id="weight" type="text" size="3" value="70" onchange="runnerUp.updateCalories(); runnerUp.updateFoodStats()"/></div>
		</div>
	  </div>
	  
	  <div> 
		<h3>Food statistics</h3>
		<table style="width:100%">
		{% for fooditem in fooditems %}
		<tr>
		  <td>
			<div style="float:left">This route burns&nbsp;</div>
			<div style="float:left; font-weight:bold" id="nr_of_{{fooditem.name}}">0</div>
			<div style="float:left; font-weight:bold">&nbsp;{{fooditem.name}}s</div>
		  </td>
		</tr>
		{% endfor %}
		<tr><td style="text-align:right"><a href="/foodupdater">Add a food item</a></td></tr>
		</table>
	  </div>
	</div>
  
  </div>
  
  </body>
</html>
